
<template>
  <div class="configurable-table">
    <el-table
      ref="elTable"
      :data="displayData"
      v-loading="loading"
      v-bind="$attrs"
      v-on="$listeners"
      style="width: 100%">
      <!-- 序号列 -->
      <el-table-column
        v-if="showIndex"
        type="index"
        :label="indexLabel"
        :width="indexWidth"
        :fixed="indexFixed"
        :align="indexAlign"
        :index="computeIndex">
      </el-table-column>

      <!-- 前置插槽：用于插入额外的列（如selection列） -->
      <slot name="prepend"></slot>

      <!-- 动态渲染列：有自定义表头的列 -->
      <template v-for="(column, index) in columns">
        <el-table-column
          v-if="column.headerSlot"
          :key="`header-${column.prop || index}`"
          :prop="column.prop"
          :width="column.width"
          :min-width="column.minWidth"
          :fixed="column.fixed"
          :align="column.align || 'left'"
          :header-align="column.headerAlign || column.align || 'left'"
          :sortable="column.sortable"
          :show-overflow-tooltip="column.showOverflowTooltip !== false">
          <!-- 自定义列内容 -->
          <template slot-scope="scope">
            <!-- 使用 render 函数 -->
            <render-cell
              v-if="column.render"
              :row="scope.row"
              :column="column"
              :index="scope.$index"
              :render="column.render" />

            <!-- 使用 formatter 格式化 -->
            <span v-else-if="column.formatter">
              {{ column.formatter(scope.row, column, scope.row[column.prop], scope.$index) }}
            </span>

            <!-- 使用 slot 插槽 -->
            <slot
              v-else-if="column.slot"
              :name="column.slot"
              :row="scope.row"
              :column="column"
              :index="scope.$index">
            </slot>

            <!-- 默认显示 -->
            <span v-else>{{ scope.row[column.prop] }}</span>
          </template>

          <!-- 自定义表头 -->
          <template slot="header" slot-scope="scope">
            <slot
              :name="column.headerSlot"
              :column="column"
              :index="scope.$index">
            </slot>
          </template>
        </el-table-column>

        <!-- 动态渲染列：普通列（使用 label） -->
        <el-table-column
          v-else
          :key="`normal-${column.prop || index}`"
          :prop="column.prop"
          :label="column.label"
          :width="column.width"
          :min-width="column.minWidth"
          :fixed="column.fixed"
          :align="column.align || 'left'"
          :header-align="column.headerAlign || column.align || 'left'"
          :sortable="column.sortable"
          :show-overflow-tooltip="column.showOverflowTooltip !== false">
          <!-- 自定义列内容 -->
          <template slot-scope="scope">
            <!-- 使用 render 函数 -->
            <render-cell
              v-if="column.render"
              :row="scope.row"
              :column="column"
              :index="scope.$index"
              :render="column.render" />

            <!-- 使用 formatter 格式化 -->
            <span v-else-if="column.formatter">
              {{ column.formatter(scope.row, column, scope.row[column.prop], scope.$index) }}
            </span>

            <!-- 使用 slot 插槽 -->
            <slot
              v-else-if="column.slot"
              :name="column.slot"
              :row="scope.row"
              :column="column"
              :index="scope.$index">
            </slot>

            <!-- 默认显示 -->
            <span v-else>{{ scope.row[column.prop] }}</span>
          </template>
        </el-table-column>
      </template>
    </el-table>

    <!-- 分页组件 -->
    <el-pagination
      v-if="showPagination && actualTotal > 0"
      :class="paginationClass"
      :style="paginationStyle"
      :current-page="currentPage"
      :page-size="pageSize"
      :page-sizes="pageSizes"
      :total="actualTotal"
      :layout="paginationLayout"
      :background="paginationBackground"
      @size-change="handleSizeChange"
      @current-change="handleCurrentChange">
    </el-pagination>
  </div>
</template>

<script>
/**
 * 可配置表格组件（支持前端/后端分页、序号列）
 *
 * @property {Array} columns - 列配置数组
 * @property {Array} data - 表格数据
 * @property {Boolean} loading - 加载状态
 *
 * 序号列相关属性：
 * @property {Boolean} showIndex - 是否显示序号列，默认 true
 * @property {String} indexLabel - 序号列标题，默认 '序号'
 * @property {String|Number} indexWidth - 序号列宽度，默认 '60'
 * @property {String} indexFixed - 序号列是否固定，默认 false
 * @property {String} indexAlign - 序号列对齐方式，默认 'center'
 *
 * 分页相关属性：
 * @property {Boolean} showPagination - 是否显示分页，默认 false
 * @property {Number} currentPage - 当前页码，支持 .sync 修饰符
 * @property {Number} pageSize - 每页条数，支持 .sync 修饰符
 * @property {Number} paginationTotal - 总条数（后端分页时必填）
 * @property {String} paginationMode - 分页模式：'frontend' 前端分页 | 'backend' 后端分页（默认）
 * @property {Array} pageSizes - 每页条数选项，默认 [10, 20, 50, 100]
 * @property {String} paginationLayout - 分页布局，默认 'total, sizes, prev, pager, next, jumper'
 * @property {Boolean} paginationBackground - 分页按钮是否有背景色，默认 false
 * @property {String} paginationClass - 分页容器自定义类名
 * @property {Object|String} paginationStyle - 分页容器自定义样式
 *
 * 分页事件：
 * @event size-change - 每页条数改变时触发，参数：新的每页条数
 * @event current-change - 当前页改变时触发，参数：新的当前页
 * @event page-change - 页码或每页条数改变时触发，参数：{ currentPage, pageSize }
 *
 * 列配置项说明：
 * {
 *   prop: String,           // 数据字段名
 *   label: String,          // 列标题
 *   width: String|Number,   // 列宽度
 *   minWidth: String|Number,// 最小列宽
 *   fixed: String|Boolean,  // 固定列 ('left' | 'right' | true)
 *   align: String,          // 对齐方式 ('left' | 'center' | 'right')
 *   headerAlign: String,    // 表头对齐方式
 *   sortable: Boolean,      // 是否可排序
 *   showOverflowTooltip: Boolean, // 是否显示溢出提示，默认 true
 *
 *   // 以下三种方式选其一来自定义内容
 *   formatter: Function,    // 格式化函数 (row, column, cellValue, index) => string
 *   render: Function,       // 渲染函数 (h, { row, column, index }) => VNode
 *   slot: String,          // 插槽名称
 *
 *   headerSlot: String      // 自定义表头插槽名称
 * }
 *
 * 使用示例：
 * // 后端分页（默认）
 * <configurable-table
 *   :columns="tableColumns"
 *   :data="tableData"
 *   :loading="loading"
 *   :show-pagination="true"
 *   :current-page.sync="pagination.current"
 *   :page-size.sync="pagination.size"
 *   :pagination-total="pagination.total"
 *   @page-change="loadData">
 * </configurable-table>
 *
 * // 前端分页
 * <configurable-table
 *   :columns="tableColumns"
 *   :data="allData"
 *   :loading="loading"
 *   :show-pagination="true"
 *   :current-page.sync="pagination.current"
 *   :page-size.sync="pagination.size"
 *   pagination-mode="frontend">
 * </configurable-table>
 */

// 渲染单元格组件
const RenderCell = {
  functional: true,
  props: {
    row: Object,
    column: Object,
    index: Number,
    render: Function
  },
  render(h, ctx) {
    const params = {
      row: ctx.props.row,
      column: ctx.props.column,
      index: ctx.props.index
    }
    return ctx.props.render(h, params)
  }
}

export default {
  name: 'ConfigurableTable',
  components: {
    RenderCell
  },
  props: {
    // ========== 表格相关 ==========
    // 列配置
    columns: {
      type: Array,
      required: true,
      default: () => []
    },
    // 表格数据
    data: {
      type: Array,
      required: true,
      default: () => []
    },
    // 加载状态
    loading: {
      type: Boolean,
      default: false
    },

    // ========== 序号列相关 ==========
    // 是否显示序号列
    showIndex: {
      type: Boolean,
      default: true
    },
    // 序号列标题
    indexLabel: {
      type: String,
      default: '序号'
    },
    // 序号列宽度
    indexWidth: {
      type: [String, Number],
      default: '60'
    },
    // 序号列是否固定
    indexFixed: {
      type: [String, Boolean],
      default: false
    },
    // 序号列对齐方式
    indexAlign: {
      type: String,
      default: 'center'
    },

    // ========== 分页相关 ==========
    // 是否显示分页
    showPagination: {
      type: Boolean,
      default: false
    },
    // 当前页码
    currentPage: {
      type: Number,
      default: 1
    },
    // 每页条数
    pageSize: {
      type: Number,
      default: 10
    },
    // 总条数
    paginationTotal: {
      type: Number,
      default: 0
    },
    // 每页条数选项
    pageSizes: {
      type: Array,
      default: () => [10, 20, 50, 100]
    },
    // 分页布局
    paginationLayout: {
      type: String,
      default: 'total, sizes, prev, pager, next, jumper'
    },
    // 分页按钮是否有背景色
    paginationBackground: {
      type: Boolean,
      default: false
    },
    // 分页容器自定义类名
    paginationClass: {
      type: String,
      default: 'pagination-container'
    },
    // 分页容器自定义样式
    paginationStyle: {
      type: [Object, String],
      default: () => ({ marginTop: '20px', textAlign: 'right' })
    },
    // 分页模式：'frontend' 前端分页（组件内部切片）| 'backend' 后端分页（默认）
    paginationMode: {
      type: String,
      default: 'backend',
      validator: (value) => ['frontend', 'backend'].includes(value)
    }
  },
  computed: {
    /**
     * 计算实际显示的数据
     * - 前端分页模式：根据 currentPage 和 pageSize 切片显示
     * - 后端分页模式：直接显示传入的 data
     */
    displayData() {
      // 如果不显示分页，直接返回全部数据
      if (!this.showPagination) {
        return this.data
      }

      // 前端分页模式：组件内部切片
      if (this.paginationMode === 'frontend') {
        const start = (this.currentPage - 1) * this.pageSize
        const end = start + this.pageSize
        return this.data.slice(start, end)
      }

      // 后端分页模式：直接显示传入的数据
      return this.data
    },

    /**
     * 计算实际总条数
     * - 前端分页模式：使用 data.length
     * - 后端分页模式：使用 paginationTotal
     */
    actualTotal() {
      if (this.paginationMode === 'frontend') {
        return this.data.length
      }
      return this.paginationTotal
    },

    /**
     * 计算序号
     * - 支持分页后序号连续
     * @param {Number} index - 表格行索引
     * @returns {Number} 计算后的序号
     */
    computeIndex() {
      return (index) => {
        if (!this.showPagination) {
          return index + 1
        }
        return (this.currentPage - 1) * this.pageSize + index + 1
      }
    }
  },
  methods: {
    // 每页条数改变
    handleSizeChange(newSize) {
      this.$emit('update:pageSize', newSize)
      this.$emit('size-change', newSize)
      this.$emit('page-change', {
        currentPage: this.currentPage,
        pageSize: newSize
      })
    },
    // 当前页改变
    handleCurrentChange(newPage) {
      this.$emit('update:currentPage', newPage)
      this.$emit('current-change', newPage)
      this.$emit('page-change', {
        currentPage: newPage,
        pageSize: this.pageSize
      })
    },

    // ========== 代理 el-table 的方法 ==========
    /**
     * 清空选择
     */
    clearSelection() {
      this.$refs.elTable && this.$refs.elTable.clearSelection()
    },
    /**
     * 切换某一行的选中状态
     */
    toggleRowSelection(row, selected) {
      this.$refs.elTable && this.$refs.elTable.toggleRowSelection(row, selected)
    },
    /**
     * 切换所有行的选中状态
     */
    toggleAllSelection() {
      this.$refs.elTable && this.$refs.elTable.toggleAllSelection()
    },
    /**
     * 清空排序条件
     */
    clearSort() {
      this.$refs.elTable && this.$refs.elTable.clearSort()
    },
    /**
     * 清空筛选条件
     */
    clearFilter(columnKey) {
      this.$refs.elTable && this.$refs.elTable.clearFilter(columnKey)
    },
    /**
     * 对 Table 进行重新布局
     */
    doLayout() {
      this.$refs.elTable && this.$refs.elTable.doLayout()
    },
    /**
     * 手动对 Table 进行排序
     */
    sort(prop, order) {
      this.$refs.elTable && this.$refs.elTable.sort(prop, order)
    }
  }
}
</script>

<style scoped lang="scss">
.configurable-table {
  width: 100%;

  // 分页容器默认样式
  .pagination-container {
    margin-top: 20px;
    text-align: right;
  }
}

// 表格对齐优化（非scoped，作用于el-table）
::v-deep .el-table {
  // 确保使用固定布局
  table-layout: fixed;

  // 表头和表体使用相同的布局方式
  .el-table__header-wrapper,
  .el-table__body-wrapper {
    .el-table__header,
    .el-table__body {
      table-layout: fixed;
    }
  }

  // 确保单元格内边距一致
  .el-table__header th,
  .el-table__body td {
    .cell {
      padding-left: 10px;
      padding-right: 10px;
      word-break: break-word; // 长文本自动换行
      line-height: 23px;
    }
  }

  // 修复固定列对齐问题
  &.el-table--border {
    .el-table__header-wrapper,
    .el-table__body-wrapper {
      .el-table__header,
      .el-table__body {
        table-layout: fixed;
      }
    }
  }

  // 修复滚动条导致的对齐问题
  .el-table__body-wrapper {
    &::-webkit-scrollbar {
      height: 8px;
      width: 8px;
    }
  }

  // 序号列居中对齐
  .el-table-column--selection .cell,
  .el-table__column--type-index .cell {
    padding-left: 10px;
    padding-right: 10px;
  }
}
</style>

